package org.zzy;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.gitlab4j.api.*;
import org.gitlab4j.api.models.*;
import org.springframework.util.CollectionUtils;
import org.zzy.webhook.WxClient;

import java.io.IOException;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import static java.lang.String.format;

/**
 * public_framework http://192.168.11.114/cloud_platform/public_platform/public_framework
 * 群组 ID：94
 * front_ends http://192.168.11.114/cloud_platform/public_platform/public_components/common_services/front_ends
 * 群组 ID：121
 * back_ends http://192.168.11.114/cloud_platform/public_platform/public_components/common_services/back_ends
 * 群组 ID：122
 * <p>
 * back_ends http://192.168.11.114/cloud_platform/public_platform/public_components/common_components/back_ends
 * 群组 ID：125
 * apps http://192.168.11.114/cloud_platform/public_platform/public_components/common_components/apps
 * 群组 ID：126
 * back_ends http://192.168.11.114/cloud_platform/public_platform/public_functions/back_ends
 * 群组 ID：116
 * front_ends http://192.168.11.114/cloud_platform/public_platform/public_functions/front_ends
 * 群组 ID：117
 * front_ends http://192.168.11.114/cloud_platform/public_platform/public_business_components/common_businesses_components/front_ends
 * 群组 ID：157
 * back_ends http://192.168.11.114/cloud_platform/public_platform/public_business_components/common_businesses_components/back_ends
 * 群组 ID：156
 * back_ends http://192.168.11.114/cloud_platform/public_platform/public_business_components/common_businesses_services/back_ends
 * 群组 ID：154
 * front_ends  http://192.168.11.114/cloud_platform/public_platform/public_business_components/common_businesses_services/front_ends
 * 群组 ID：155
 * public_framework http://192.168.11.114/cloud_platform/road_cloud/advanced_road_cloud/public_framework
 * 群组 ID：93
 * front_ends  http://192.168.11.114/cloud_platform/road_cloud/advanced_road_cloud/businesses/front_ends
 * 群组 ID：99
 * back_ends http://192.168.11.114/cloud_platform/road_cloud/advanced_road_cloud/businesses/back_ends
 * 群组 ID：100
 * apps http://192.168.11.114/cloud_platform/road_cloud/advanced_road_cloud/businesses/apps
 * 群组 ID：101
 * clients http://192.168.11.114/cloud_platform/road_cloud/advanced_road_cloud/businesses/clients
 * 群组 ID：159
 */

@Slf4j
public class App {

    /*
    所有
    */
    public static final String ALL_BRANCH = "all";
    /*
    开发分支
     */
    public static final String DEV_BRANCH = "develop";
    /*
    测试分支
     */
    public static final String RELEASE_BRANCH = "release";
    /*
    预生产分支
    */
    public static final String PREPRODUCT_BRANCH = "preproduct";
    /*
    标签名称
    */
    public static final String TAG_NAME = "tag_preproduct_V2.1.0.2_202301132100";
    /*
    企业微信markdown 模板
     */

    public static String MSG_TEMPLATE =
            " #### <font color=warning>%s </font>已发起合并请求,请相关同事注意！" +
                    "\n> <font color=comment> 类型：</font><font color=info>%s</font>" +
                    "\n> <font color=comment> 状态：</font><font color=info>%s</font>" +
                    "\n> <font color=comment> 发起人：</font><font color=info>%s</font>" +
                    "\n> <font color=comment> 地址：</font><font color=info>[点击这里去查看->](%s)</font>";

    public static String TAG_MESSAGE_TEMPLATE =
            " #### <font color=warning>%s </font>发起打标签！" +
                    "\n> <font color=comment> 服务器返回：</font><font color=info>%s</font>";

    public static final String RELEASE_TITLE = "版本发布合并release-->preproduct";
    public static final String RELEASE_DESC = "当前合并请求为版本发布合并请求release-->preproduct";
    public static final String DEV_TITLE = "版本发布合并develop-->release";
    public static final String DEV_DESC = "当前合并请求为版本发布合并请求develop-->release";
    public static final String CANNOT_BE_MERGED = "cannot_be_merged";
    public static final String CAN_BE_MERGED = "can_be_merged";
    public static final Boolean AUTO_CLOSE = false;
    public static GitLabApi gitlabApi = null;


    public static void main(String[] args) throws GitLabApiException {

        //延时发布
        delayPublish(ALL_BRANCH, 23, 30);
        //立刻发布
//        nowPublish(ALL_BRANCH);
        //全局打标签
//        tag(PREPRODUCT_BRANCH);


    }

    /**
     * @description: 〈打标签〉
     * @author: zhuzhaoyang
     * @date: 2023/1/13 16:43
     */
    private static void tag(String targetBranch) {
        initAndGetCurrentUser();
        List<Project> projectList = getProjectList(gitlabApi);
        List<String> userList = new ArrayList<>();
        userList.add("@all");
        for (Project project : projectList) {

            try {
                Thread.sleep(3000);
                TagsApi tagsApi = gitlabApi.getTagsApi();
                Tag tag = tagsApi.createTag(project.getId(), TAG_NAME, targetBranch);
                log.debug("打标签返回:{}", tag);
                String tagStr = JSON.toJSONString(tag);
                WxClient.sendMarkdownMessage(format(TAG_MESSAGE_TEMPLATE,
                                project.getName(),
                                tagStr),
                        userList);
            }  catch (GitLabApiException | InterruptedException e) {
                e.printStackTrace();
                WxClient.sendMarkdownMessage(format(TAG_MESSAGE_TEMPLATE,
                                project.getName(),
                                e.getMessage()),
                        userList);
                log.error("打标签错误:{}", e.getMessage());
            }
        }
    }


    /**
     * @description: 〈延时启动〉
     * @author: zhuzhaoyang
     * @date: 2023/1/13 16:36
     */
    private static void delayPublish(String targetBranch, Integer hour, Integer minute) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, hour);
        calendar.set(Calendar.MINUTE, minute);
        calendar.set(Calendar.SECOND, 0);
        Date time = calendar.getTime();
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                start(targetBranch);
            }
        }, time, 1000 * 60 * 60 * 24);
    }

    /**
     * @description: 〈立刻执行〉
     * @author: zhuzhaoyang
     * @date: 2023/1/13 16:36
     */
    private static void nowPublish(String targetBranch) {
        start(targetBranch);
    }

    private static void start(String param) {
        try {

            System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "debug");
            User currentUser = initAndGetCurrentUser();
            if (ALL_BRANCH.equals(param)) {
                doDev2Release(currentUser);
                Thread.sleep(3000);
                doRelease2Preproduct(currentUser);
            } else if (RELEASE_BRANCH.equals(param)) {
                doDev2Release(currentUser);
                Thread.sleep(3000);
            } else if (PREPRODUCT_BRANCH.equals(param)) {
                doRelease2Preproduct(currentUser);
                Thread.sleep(3000);
            } else {
                int type = getType();
                String s = type == 1 ? "develop提交合并到release" : type == 2 ? "release提交合并到preproduct" : "输入错误！！";
                log.debug("\n您选择的提交类型是：" + s + "\n");

                if (type == 1) {
                    doDev2Release(currentUser);
                } else if (type == 2) {
                    doRelease2Preproduct(currentUser);
                }
            }


//            exitGitlab();
        } catch (GitLabApiException | InterruptedException e) {
            log.debug("gitlab 请求错误 :{}", e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 执行完毕之后退出
     */
    private static void exitGitlab() {
        log.debug("\n输入任意键退出");
        Scanner scanner = new Scanner(System.in);
        String in = scanner.nextLine();
        System.exit(0);
    }

    private static User initAndGetCurrentUser() {
        try {
            log.debug("\n二、请输入你的Gitlab密码,获取步骤：\n" +
                    "①  登录您的gitlab\n" +
                    "②  点击用户头像-Setting\n" +
                    "③  进入AccessToken菜单 ，输入令牌名称，勾选令牌使用场景 ，点击Create personal access token按钮生成令牌\n" +
                    "④  将生成的access token 保存到自己电脑上，注意：离开该页面您将无法在找到该令牌。\n");
//            Scanner scanner1 = new Scanner(System.in);
//            String accessToken = scanner1.nextLine();
            String accessToken = "KLkt-3HrYrcDTKKDMxH9";// "NiUpieKa31ZKfqbd3TP9";

            gitlabApi = init(accessToken);
            User user = gitlabApi.getUserApi().getCurrentUser();
            log.debug("\n当前登录人员信息为:{}", user);
            return user;
        } catch (Exception e) {
            log.debug("令牌错误:错误原因:{}", e.getMessage());
            log.error("令牌错误:错误原因:{}", e.getMessage());
            log.debug("令牌错误:请重新输入...");
            return initAndGetCurrentUser();
        }
    }

    private static int getType() {
        log.debug("\n一、请选择您要提交的发布版本（输入1 or 2）\n" +
                "【1】:develop提交合并到release\n" +
                "【2】:release提交合并到preproduct\n");
        Scanner scanner = new Scanner(System.in);
        int type;
        try {
            type = scanner.nextInt();
        } catch (Exception e) {
            log.debug("输入错误，请重新输入\n");
            return getType();
        }

        if (type != 1 && type != 2) {
            log.debug("输入错误，请重新输入\n");
            return getType();
        }
        return type;
    }

    private static void doRelease2Preproduct(User currentUser) throws InterruptedException, GitLabApiException {
        String handler = currentUser.getName() + "-" + currentUser.getUsername();
        int i = 0;
        List<String> userList = new ArrayList<>();
        userList.add("18013060182");
        userList.add("@all");
        List<Project> projectList = getProjectList(gitlabApi);
        List<String> unMergeList = new ArrayList<>();
        //最后手动触发
        unMergeList.add("jjsk_enterprise_center");
        unMergeList.add("road_cloud_main_app");
        unMergeList.add("jjsk_workflow");
        for (Project project : projectList) {
            String projectName = project.getName();
            projectName = ++i + "、" + projectName;
            Integer projectId = project.getId();
            if (projectId != null) {
                try {
                    MergeRequestApi mergeRequestApi = gitlabApi.getMergeRequestApi();
                    MergeRequest mergeRequest = mergeRequestApi.createMergeRequest(projectId,
                            RELEASE_BRANCH,
                            PREPRODUCT_BRANCH,
                            RELEASE_TITLE,
                            RELEASE_DESC,
                            currentUser.getId()
                    );
                    log.debug("提merge成功,返回结果为:{}", mergeRequest);
                    MergeRequest mergeRequestChanges = mergeRequestApi.getMergeRequestChanges(project.getId(), mergeRequest.getIid());
                    log.debug("当前项目{},当前合并请求的changes为:{}", projectName, mergeRequestChanges);
                    List<Commit> commits = mergeRequestApi.getCommits(project.getId(), mergeRequest.getIid());
                    log.debug("当前项目{},当前合并请求的commits为:{}", projectName, commits);
                    List<Diff> changes = mergeRequestChanges.getChanges();
                    if (CollectionUtils.isEmpty(changes) && CollectionUtils.isEmpty(commits)) {
                        log.debug("当前release-->preproduct无修改");
                        MergeRequest updateMergeRequest = null;
                        try {
                            updateMergeRequest = gitlabApi.getMergeRequestApi().updateMergeRequest(
                                    projectId,
                                    mergeRequest.getIid(),
                                    new MergeRequestParams()
                                            .withStateEvent(Constants.StateEvent.CLOSE)
                                            .withTitle("release-->preproduct无变化,已关闭")
                            );
                            log.debug("取消merge请求,返回结果为:{}", updateMergeRequest);
                            WxClient.sendMarkdownMessage(format(MSG_TEMPLATE,
                                    projectName,
                                    RELEASE_TITLE,
                                    "无变化,已关闭合并请求,无需处理",
                                    handler,
                                    project.getWebUrl()
                            ), userList);
                        } catch (GitLabApiException e) {
                            log.debug("关闭异常:{}", e.getMessage());
                            WxClient.sendMarkdownMessage(format(MSG_TEMPLATE,
                                    projectName,
                                    RELEASE_TITLE,
                                    "无变化,自动关闭失败,请手动处理;失败原因:" + e.getMessage(),
                                    handler,
                                    updateMergeRequest.getWebUrl()
                            ), userList);
                        }
                    } else {
                        WxClient.sendMarkdownMessage(format(MSG_TEMPLATE,
                                projectName,
                                RELEASE_TITLE,
                                "请查看后合并...",
                                handler,
                                mergeRequest.getWebUrl()
                        ), userList);

                        //*******************开启自动合并****************/
                        try {
                            //如果项目在非合并列表里 就不合并 !"jjsk_enterprise_center".equals(project.getName())
                            if (!unMergeList.contains(project.getName())) {
                                MergeRequest mergeRequest1 = gitlabApi.getMergeRequestApi().acceptMergeRequest(projectId, mergeRequest.getIid());
                                log.debug("自动合并请求返回结果为{}", mergeRequest1);
                            }
                        } catch (GitLabApiException e) {
                            log.debug("出现错误:{}", e.getMessage())
                            ;
                            WxClient.sendMarkdownMessage(format(MSG_TEMPLATE,
                                    projectName,
                                    DEV_TITLE,
                                    "当前项目存在:" + (e.getMessage().equals("405 Method Not Allowed") ? "冲突" : e.getMessage()) + "问题",
                                    handler,
                                    project.getWebUrl()
                            ), userList);
                        }
                    }

                } catch (GitLabApiException e) {
                    log.debug("出现错误:{}", e.getMessage());
                    WxClient.sendMarkdownMessage(format(MSG_TEMPLATE,
                            projectName,
                            RELEASE_TITLE,
                            "合并发起失败,请手动处理,失败原因" + e.getMessage(),
                            handler,
                            project.getWebUrl()
                    ), userList);
                }

            }
            int sleep = 3;
            for (int j = 0; j <= sleep; j++) {
                log.debug(String.valueOf(sleep - j));
                Thread.sleep(1000);
            }
        }

    }


    private static void doDev2Release(User currentUser) throws InterruptedException, GitLabApiException {
        List<String> unMergeList = new ArrayList<>();
        //最后手动触发
        unMergeList.add("jjsk_enterprise_center");
        unMergeList.add("road_cloud_main_app");
        unMergeList.add("jjsk_workflow");
        String handler = currentUser.getName() + "-" + currentUser.getUsername();
        int i = 0;
        List<String> userList = new ArrayList<>();
        userList.add("18013060182");
        userList.add("@all");
        List<Project> projectList = getProjectList(gitlabApi);

        for (Project project : projectList) {
            String projectName = project.getName();
            projectName = ++i + "、" + projectName;
            Integer projectId = project.getId();
            if (projectId != null) {
                try {
                    MergeRequestApi mergeRequestApi = gitlabApi.getMergeRequestApi();
                    MergeRequest mergeRequest = mergeRequestApi.createMergeRequest(projectId,
                            DEV_BRANCH,
                            RELEASE_BRANCH,
                            DEV_TITLE,
                            DEV_DESC,
                            currentUser.getId()
                    );
                    log.debug("当前项目{},提交merge成功,返回结果为:{}", projectName, mergeRequest);
                    MergeRequest mergeRequestChanges = mergeRequestApi.getMergeRequestChanges(project.getId(), mergeRequest.getIid());
                    log.debug("当前项目{},当前合并请求的changes为:{}", projectName, mergeRequestChanges);
                    List<Commit> commits = mergeRequestApi.getCommits(project.getId(), mergeRequest.getIid());
                    log.debug("当前项目{},当前合并请求的commits为:{}", projectName, commits);
                    List<Diff> changes = mergeRequestChanges.getChanges();
                    if (CollectionUtils.isEmpty(changes) && CollectionUtils.isEmpty(commits)) {
                        log.debug("当前项目{},当前dev-->release 无修改", projectName);
                        MergeRequest updateMergeRequest = null;
                        try {
                            updateMergeRequest = gitlabApi.getMergeRequestApi().updateMergeRequest(
                                    projectId,
                                    mergeRequest.getIid(),
                                    new MergeRequestParams()
                                            .withStateEvent(Constants.StateEvent.CLOSE)
                                            .withTitle("dev-->release无变化,已关闭")
                            );
                            log.debug("取消merge请求,返回结果为:{}", updateMergeRequest);
                            WxClient.sendMarkdownMessage(format(MSG_TEMPLATE,
                                    projectName,
                                    DEV_TITLE,
                                    "无变化,已关闭合并请求,无需处理",
                                    handler,
                                    project.getWebUrl()
                            ), userList);
                        } catch (GitLabApiException e) {
                            log.debug("关闭异常:{}", e.getMessage());
                            WxClient.sendMarkdownMessage(format(MSG_TEMPLATE,
                                    projectName,
                                    DEV_TITLE,
                                    "无变化,自动关闭失败,请手动处理;失败原因:" + e.getMessage(),
                                    handler,
                                    updateMergeRequest.getWebUrl()
                            ), userList);
                        }

                    } else {
                        WxClient.sendMarkdownMessage(format(MSG_TEMPLATE,
                                projectName,
                                DEV_TITLE,
                                "请查看后合并...",
                                handler,
                                mergeRequest.getWebUrl()
                        ), userList);
                        //*******************开启自动合并****************/
                        try {
                            //如果项目在非合并列表里 就不合并 !"jjsk_enterprise_center".equals(project.getName())
                            if (!unMergeList.contains(project.getName())) {
                                MergeRequest mergeRequest1 = gitlabApi.getMergeRequestApi().acceptMergeRequest(projectId, mergeRequest.getIid());
                                log.debug("自动合并请求返回结果为{}", mergeRequest1);
                            }
                        } catch (GitLabApiException e) {
                            log.debug("出现错误:{}", e.getMessage());
                            WxClient.sendMarkdownMessage(format(MSG_TEMPLATE,
                                    projectName,
                                    DEV_TITLE,
                                    "当前项目存在:" + (e.getMessage().equals("405 Method Not Allowed") ? "冲突" : e.getMessage()) + "问题",
                                    handler,
                                    project.getWebUrl()
                            ), userList);
                        }
                    }

                } catch (GitLabApiException e) {
                    log.debug("出现错误:{}", e.getMessage());
                    WxClient.sendMarkdownMessage(format(MSG_TEMPLATE,
                            projectName,
                            DEV_TITLE,
                            "合并发起失败,请手动处理,失败原因:" + e.getMessage(),
                            handler,
                            project.getWebUrl()
                    ), userList);
                }

            }
            int sleep = 3;
            for (int j = 0; j <= sleep; j++) {
                log.debug(String.valueOf(sleep - j));
                Thread.sleep(1000);
            }
        }
    }

    private static List<Project> getProjectList(GitLabApi gitlabApi) {
        List<Project> projectList = new ArrayList<>();
        try {
            List<Project> myCloudPlatformProjectList94 = gitlabApi.getGroupApi().getProjects(94);
            List<Project> myCloudPlatformProjectList121 = gitlabApi.getGroupApi().getProjects(121);
            List<Project> myCloudPlatformProjectList122 = gitlabApi.getGroupApi().getProjects(122);
            List<Project> myCloudPlatformProjectList125 = gitlabApi.getGroupApi().getProjects(125);
            List<Project> myCloudPlatformProjectList126 = gitlabApi.getGroupApi().getProjects(126);
            List<Project> myCloudPlatformProjectList116 = gitlabApi.getGroupApi().getProjects(116);
            List<Project> myCloudPlatformProjectList117 = gitlabApi.getGroupApi().getProjects(117);
            List<Project> myCloudPlatformProjectList157 = gitlabApi.getGroupApi().getProjects(157);
            List<Project> myCloudPlatformProjectList156 = gitlabApi.getGroupApi().getProjects(156);
            List<Project> myCloudPlatformProjectList154 = gitlabApi.getGroupApi().getProjects(154);
            List<Project> myCloudPlatformProjectList155 = gitlabApi.getGroupApi().getProjects(155);
            List<Project> myCloudPlatformProjectList93 = gitlabApi.getGroupApi().getProjects(93);
            List<Project> myCloudPlatformProjectList99 = gitlabApi.getGroupApi().getProjects(99);
            List<Project> myCloudPlatformProjectList100 = gitlabApi.getGroupApi().getProjects(100);
            List<Project> myCloudPlatformProjectList101 = gitlabApi.getGroupApi().getProjects(101);
            List<Project> myCloudPlatformProjectList159 = gitlabApi.getGroupApi().getProjects(159);
            myCloudPlatformProjectList94.addAll(myCloudPlatformProjectList121);
            myCloudPlatformProjectList94.addAll(myCloudPlatformProjectList122);
            myCloudPlatformProjectList94.addAll(myCloudPlatformProjectList125);
            myCloudPlatformProjectList94.addAll(myCloudPlatformProjectList126);
            myCloudPlatformProjectList94.addAll(myCloudPlatformProjectList116);
            myCloudPlatformProjectList94.addAll(myCloudPlatformProjectList117);
            myCloudPlatformProjectList94.addAll(myCloudPlatformProjectList157);
            myCloudPlatformProjectList94.addAll(myCloudPlatformProjectList156);
            myCloudPlatformProjectList94.addAll(myCloudPlatformProjectList154);
            myCloudPlatformProjectList94.addAll(myCloudPlatformProjectList155);
            myCloudPlatformProjectList94.addAll(myCloudPlatformProjectList93);
            myCloudPlatformProjectList94.addAll(myCloudPlatformProjectList99);
            myCloudPlatformProjectList94.addAll(myCloudPlatformProjectList100);
            myCloudPlatformProjectList94.addAll(myCloudPlatformProjectList101);
            myCloudPlatformProjectList94.addAll(myCloudPlatformProjectList159);

            log.debug("共计 : {}", myCloudPlatformProjectList94.size());
            return myCloudPlatformProjectList94;
        } catch (GitLabApiException e) {
            e.printStackTrace();
            log.error("获取项目列表异常:{}", e.getMessage());
        }
        return projectList;
    }

    /**
     * 初始化gitlabApi
     *
     * @param accessToken
     * @return
     */
    private static GitLabApi init(String accessToken) {
        log.debug("初始化gitlabAPI");
        return new GitLabApi("http://192.168.11.114", accessToken);
    }

}
